﻿using System;
using System.Linq.Expressions;
using System.Threading;
using Entropy.Ext;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DelegateToExpression.Test
{
	[TestClass]
	public class UnitTest1
	{
        private static readonly Func<Expression, string> debugView = BuildDebugView();

		private static Func<Expression, string> BuildDebugView()
		{
			var parameter = Expression.Parameter(typeof(Expression), "e");
			return Expression.Lambda<Func<Expression, string>>(Expression.Property(parameter, "DebugView"), parameter).Compile();
		}

	    protected static void Test(string expected, Delegate compiled)
	    {
            var decompiled = compiled.ToExpression();
            Assert.AreEqual(expected.Trim(), debugView(decompiled));
	    }

		protected static void Test(Expression expected, Delegate compiled)
		{
			var decompiled = compiled.ToExpression();

			Assert.AreEqual(expected.ToString(), decompiled.ToString());
			Assert.AreEqual(debugView(expected), debugView(decompiled));
		}

        [TestMethod]
		public void CanUseEmptyIf()
		{
		    bool c = false;
			Action action = () =>
			{
			    if (c)
			    {
			        return;
			    }

			};
		    
            var expr = action.ToExpression();

		    const string expected = @".Lambda #Lambda1<System.Action`1[DelegateToExpression.Test.UnitTest1+<>c__DisplayClass1]>(DelegateToExpression.Test.UnitTest1+<>c__DisplayClass1 $this)
{
    .Block(System.Boolean $var0) {
        $var0 = $this.c == False;
        .If ($var0 != False) {
            .Default(System.Void)
        } .Else {
            .Default(System.Void)
        }
    }
}";
            Test(expected, action);
		}

        [TestMethod]
		public void CanUseIfWithDifferentBranchesAssignAndVoid()
		{
		    bool c = false;
			Action action = () =>
			{
			    if (c)
			    {
			        var d = c;
                }

			};
		    
            var expr = action.ToExpression();

            const string expected = @".Lambda #Lambda1<System.Action`1[DelegateToExpression.Test.UnitTest1+<>c__DisplayClass4]>(DelegateToExpression.Test.UnitTest1+<>c__DisplayClass4 $this)
{
    .Block(
        System.Boolean $var0,
        System.Boolean $var1) {
        $var1 = $this.c == False;
        .If ($var1 != False) {
            .Default(System.Void)
        } .Else {
            $var0 = $this.c
        }
    }
}";
            Test(expected, action);
		}
	}
}
